(** Cache management for Pickles proof system keys.

    This module provides caching functionality for both proving and verification
    keys used in the Pickles recursive SNARK system. It handles two types of
    circuits:
    - Step circuits: intermediate proof steps (using Tick field)
    - Wrap circuits: final proof wrapping (using Tock field)

    The cache system supports disk persistence and lazy generation of keys. *)

(** Step circuit key caching.

    Step circuits are the intermediate proof steps in the recursive composition.
    They operate over the Tick field and handle the main computation logic. *)
module Step : sig
  (** Key types and identifiers for caching. *)
  module Key : sig
    (** Proving key identifiers and metadata. *)
    module Proving : sig
      (** A proving key is uniquely identified by:
          - Type ID: unique identifier for the circuit type
          - Header: metadata about the SNARK keys
          - Index: position in the step chain
          - Constraint system: the R1CS constraint system for the circuit *)
      type t =
        Core_kernel.Type_equal.Id.Uid.t
        * Snark_keys_header.t
        * int
        * Backend.Tick.R1CS_constraint_system.t

      (** Convert proving key identifier to a human-readable string. *)
      val to_string : t -> string
    end

    (** Verification key identifiers and metadata. *)
    module Verification : sig
      (** A verification key is uniquely identified by:
          - Type ID: unique identifier for the circuit type
          - Header: metadata about the SNARK keys
          - Index: position in the step chain
          - Hash: MD5 hash for integrity checking *)
      type t =
        Core_kernel.Type_equal.Id.Uid.t
        * Snark_keys_header.t
        * int
        * Core_kernel.Md5.t

      (** Convert verification key identifier to a human-readable string. *)
      val to_string : t -> string
    end
  end

  (** Type for disk-storable proving keys.
      Maps proving key identifiers to actual Tick keypairs. *)
  type storable =
    (Key.Proving.t, Backend.Tick.Keypair.t) Key_cache.Sync.Disk_storable.t

  (** Type for disk-storable verification keys.
      Maps verification key identifiers to Kimchi verifier indices. *)
  type vk_storable =
    ( Key.Verification.t
    , Kimchi_bindings.Protocol.VerifierIndex.Fp.t )
    Key_cache.Sync.Disk_storable.t

  (** Default disk storage handler for proving keys.

      When writing keys to disk, this storage handler will optionally dump
      extra circuit data (constraint system details) based on the
      MINA_DUMP_CIRCUIT_DATA environment variable. The dumping is disabled
      by default. Set MINA_DUMP_CIRCUIT_DATA to "true", "1", or "yes" to enable. *)
  val storable : storable

  (** Default disk storage handler for verification keys. *)
  val vk_storable : vk_storable

  (** Read keys from cache or generate them if not found.

      @param prev_challenges Number of previous challenges in the circuit
      @param Key_cache.Spec.t list List of cache specifications (paths, URLs, etc.)
      @param s_p Optional custom storage handler for proving keys
      @param s_v Optional custom storage handler for verification keys
      @param lazy_mode If true, defer key generation until actually needed
      @param Key.Proving.t Promise.t Lazy.t Lazy promise for generating proving key
      @param Key.Verification.t Promise.t Lazy.t Lazy promise for generating
      verification key

      @return A pair of lazy promises containing:
        - Proving key with status indicator
        - Verification key with status indicator

      Status indicators:
        - [`Cache_hit]: Key was found in cache
        - [`Generated_something]: Key was generated (possibly by another
          process)
        - [`Locally_generated]: Key was generated by this process *)
  val read_or_generate :
       prev_challenges:int
    -> Key_cache.Spec.t list
    -> ?s_p:storable
    -> ?s_v:vk_storable
    -> ?lazy_mode:bool
    -> Key.Proving.t Promise.t Lazy.t
    -> Key.Verification.t Promise.t Lazy.t
    -> ( Impls.Step.Proving_key.t
       * ([> `Cache_hit | `Generated_something | `Locally_generated ] as 'e) )
       Promise.t
       Lazy.t
       * ( Kimchi_bindings.Protocol.VerifierIndex.Fp.t
         * ([> `Cache_hit | `Generated_something | `Locally_generated ] as 'e)
         )
         Promise.t
         Lazy.t
end

(** Wrap circuit key caching.

    Wrap circuits provide the final wrapping step that produces the recursive
    proof. They operate over the Tock field and handle proof aggregation. *)
module Wrap : sig
  (** Key types and identifiers for wrap circuit caching. *)
  module Key : sig
    (** Proving key identifiers for wrap circuits. *)
    module Proving : sig
      (** A wrap proving key is uniquely identified by:
          - Type ID: unique identifier for the circuit type
          - Header: metadata about the SNARK keys
          - Constraint system: the R1CS constraint system for the wrap
            circuit *)
      type t =
        Core_kernel.Type_equal.Id.Uid.t
        * Snark_keys_header.t
        * Backend.Tock.R1CS_constraint_system.t

      (** Convert proving key identifier to a human-readable string. *)
      val to_string : t -> string
    end

    (** Verification key identifiers for wrap circuits. *)
    module Verification : sig
      (** A wrap verification key is uniquely identified by:
          - Type ID: unique identifier for the circuit type
          - Header: metadata about the SNARK keys
          - Hash: MD5 hash for integrity checking *)
      type t =
        Core_kernel.Type_equal.Id.Uid.t
        * Snark_keys_header.t
        * Core_kernel.Md5.t
      [@@deriving sexp]

      (** Convert verification key identifier to a human-readable string. *)
      val to_string : t -> string

      (** Check equality of two verification key identifiers. *)
      val equal : t -> t -> bool
    end
  end

  (** Type for disk-storable wrap proving keys.
      Maps proving key identifiers to actual Tock keypairs. *)
  type storable =
    (Key.Proving.t, Backend.Tock.Keypair.t) Key_cache.Sync.Disk_storable.t

  (** Type for disk-storable wrap verification keys.
      Maps verification key identifiers to verification key structures. *)
  type vk_storable =
    (Key.Verification.t, Verification_key.t) Key_cache.Sync.Disk_storable.t

  (** Default disk storage handler for wrap proving keys.

      When writing keys to disk, this storage handler will optionally dump
      extra circuit data (constraint system details) based on the
      MINA_DUMP_CIRCUIT_DATA environment variable. The dumping is disabled
      by default. Set MINA_DUMP_CIRCUIT_DATA to "true", "1", or "yes" to enable. *)
  val storable : storable

  (** Default disk storage handler for wrap verification keys. *)
  val vk_storable : vk_storable

  (** Read wrap keys from cache or generate them if not found.

      @param prev_challenges Number of previous challenges in the wrap circuit
      @param Key_cache.Spec.t list List of cache specifications (paths, URLs,
      etc.)
      @param s_p Optional custom storage handler for proving keys
      @param s_v Optional custom storage handler for verification keys
      @param lazy_mode If true, defer key generation until actually needed
      @param Key.Proving.t Promise.t Lazy.t Lazy promise for generating proving
      key
      @param Key.Verification.t Promise.t Lazy.t Lazy promise for generating
      verification key

      @return A pair of lazy promises containing:
        - Wrap proving key with status indicator
        - Wrap verification key with status indicator

      Status indicators:
        - [`Cache_hit]: Key was found in cache
        - [`Generated_something]: Key was generated (possibly by another
          process)
        - [`Locally_generated]: Key was generated by this process *)
  val read_or_generate :
       prev_challenges:Core_kernel.Int.t
    -> Key_cache.Spec.t list
    -> ?s_p:storable
    -> ?s_v:vk_storable
    -> ?lazy_mode:bool
    -> Key.Proving.t Promise.t Lazy.t
    -> Key.Verification.t Promise.t Lazy.t
    -> ( Impls.Wrap.Proving_key.t
       * [> `Cache_hit | `Generated_something | `Locally_generated ] )
       Promise.t
       Lazy.t
       * ( Verification_key.Stable.V2.t
         * [> `Cache_hit | `Generated_something | `Locally_generated ] )
         Promise.t
         Lazy.t
end
